\documentclass[a4paper,12pt]{article}

\usepackage[margin=1.5cm]{geometry}
\usepackage{listings}
\usepackage{enumitem}
\usepackage[colorlinks, urlcolor=blue]{hyperref}
\usepackage{tikz}

\usetikzlibrary{arrows,decorations.pathmorphing,backgrounds,positioning,fit,shapes,calc}

\title{Resize ext3 Partition}
\author{Chen Rushan\\chenrsster@gmail.com}
\date{2009.12.06 10:17}

\setlength{\parskip}{1.2ex}
\setlength{\parindent}{0pt}

\lstset{
    frame=single, framesep=0pt, framexleftmargin=-1pt, framextopmargin=3pt,
    framexbottommargin=3pt, aboveskip=0.5cm, belowskip=0.2cm, columns=flexible,
    basicstyle=\ttfamily
}

\begin{document}

\maketitle

\section{Shrinking an ext3 partition}

    I'm going to shrink partition {\em /dev/sdb1}. Before shrinking, we must
    have some idea about the original system, especially the size of the
    file system that are already used, to make sure that shrinking doesn't
    cause data lost.

    To gather such information, run \verb=df -h /dev/sdb1=, which outputs:

    \begin{lstlisting}[gobble=3]
    Filesystem            Size  Used Avail Use% Mounted on
    /dev/sdb1              56G   35G   18G   66%  /mnt
    \end{lstlisting}

    From the output, we know that the partition size after shrinking should be
    no less than 35G, to go sure, specify at lease 37G when shrinking.

    Now let's begin. Shrinking a partition consists of two steps:

    \begin{enumerate}[topsep=0pt, itemsep=0pt]
        \item Shrink the file system on that partition, which can be done by
            using command \verb=resize2fs=.
        \item Shrink the partition, which can be done by using command
            \verb=fdisk=.
    \end{enumerate}

    Since my original file system is of ext3 type and \verb=resize2fs= is only
    able to deal with ext2, we need to turn the file system into ext2 type by
    running:

    \begin{lstlisting}[gobble=3]
    tune2fs -O ^has_journal /dev/sdb1
    \end{lstlisting}

    This command removes the journal feature of the file system.

    If you run \verb=resize2fs= now, you'll be informed to run \verb=e2fsck= to
    check the file system first as:

    \begin{lstlisting}[gobble=3]
    e2fsck -f /dev/sdb1
    \end{lstlisting}

    Now it's time to resize the partition, run:

    \begin{lstlisting}[gobble=3]
    resize2fs /dev/sdb1 37G
    \end{lstlisting}

    The output of this command looks like:

    \begin{lstlisting}[gobble=3]
    resize2fs 1.41.9 (22-Aug-2009)
    Resizing the filesystem on /dev/sdb1 to 9699328 (4k) blocks.
    The filesystem on /dev/sdb1 is now 9699328 blocks long.
    \end{lstlisting}

    Note down the number 9699328 somewhere, cuz it'll be used when resizing the
    underlying partition. Now run fdisk as:

    \begin{lstlisting}[gobble=3]
    fdisk /dev/sdb1
    \end{lstlisting}

    The output looks like the following, in that, commands that I entered are shown in
    a box.

    \begin{lstlisting}[gobble=3, escapechar=\%]
    The number of cylinders for this disk is set to 7296.
    There is nothing wrong with that, but this is larger than 1024,
    and could in certain setups cause problems with:
    1) software that runs at boot time (e.g., old versions of LILO)
    2) booting and partitioning software from other OSs
       (e.g., DOS FDISK, OS/2 FDISK)

    Command (m for help): %\framebox{p}%

    Disk /dev/sdb: 60.0 GB, 60011642880 bytes
    255 heads, 63 sectors/track, 7296 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Disk identifier: 0xcccdcccd
       Device Boot      Start         End      Blocks   Id  System
    /dev/sdb1               1        7296    58605088+  83  Linux

    Command (m for help): %\framebox{d}%
    Selected partition 1

    Command (m for help): %\framebox{n}%
    Command action
       e   extended
       p   primary partition (1-4)
    %\framebox{p}%
    Partition number (1-4): %\framebox{1}%
    First cylinder (1-7296, default 1): %\framebox{press <enter> here}%
    Using default value 1
    Last cylinder, +cylinders or +size{K,M,G} (1-7296, default 7296): %\framebox{+38797312K}%

    Command (m for help): %\framebox{w}%
    The partition table has been altered!

    Calling ioctl() to re-read partition table.
    Syncing disks.
    \end{lstlisting}

    The number {\em 38797312K} of last cylinder input above is the result of 4
    multiplied by {\em 9699328}, which is the output produced by command
    \verb=resize2fs=, here, we need to multiply a 4, since {\em 9699328} is in
    units of 4K-block. To go sure, you can choose a number which is bigger that
    {\em 38797312K}.

    Generally, at this point, the size of the file system will be smaller than
    underlying partition, although during resizing, they are specified to have
    the same size. So to make the partition be fully used, we need to resize the
    file system again. Still, call \verb=e2fsck= first:

    \begin{lstlisting}[gobble=3]
    e2fsck -f /dev/sdb1
    \end{lstlisting}

    and then:

    \begin{lstlisting}[gobble=3]
    resize2fs /dev/sdb1
    \end{lstlisting}

    In the above command, we don't specify a size as last time, this will cause
    \verb=resize2fs= to use the biggest possible size. The output of this command
    is as follows, from which we can find that the file system is enlarged.
    
    \begin{lstlisting}[gobble=3]
    resize2fs 1.41.9 (22-Aug-2009)
    Resizing the filesystem on /dev/sdb1 to 9701244 (4k) blocks.
    The filesystem on /dev/sdb1 is now 9701244 blocks long.
    \end{lstlisting}

    The final step is to turn the final system back into ext3 by running:

    \begin{lstlisting}[gobble=3]
    tune2fs -j /dev/sdb1
    \end{lstlisting}

\section*{References}

    \begin{itemize}[leftmargin=3ex]
        \item \href{http://tldp.org/HOWTO/html_single/Large-Disk-HOWTO/#ss14.2}
                   {http://tldp.org/HOWTO/html\_single/Large-Disk-HOWTO/\#ss14.2}
        \item \href{http://www.howtoforge.com/linux_resizing_ext3_partitions}
                   {http://www.howtoforge.com/linux\_resizing\_ext3\_partitions}
    \end{itemize}

\appendix
\section*{Appendix}

\section{fdisk sees much more room than df?}

    {\em fdisk} will tell you the total number of blocks on this partition of
    the disk, while {\em df} only tells you the maximum number of blocks on this
    partition that are usable to users. For example:

    \verb=fdisk -s /dev/sdb1= outputs:

    \begin{lstlisting}[gobble=3]
    58605088
    \end{lstlisting}
    (the above number is in units of 1K-block)

    while \verb=df /dev/sdb1= gives you:

    \begin{lstlisting}[gobble=3]
    Filesystem           1K-blocks      Used Available Use% Mounted on
    /dev/sdb1             57685532  35970328  18784952   66%  /mnt
    \end{lstlisting}

    Note that the number of 1K-blocks output by {\em df} is smaller than {\em
    fdisk}, the difference between these two numbers is {\em 58605088 -
    57685532}, that is {\em 919556} 1K-blocks, which are used for inodes and
    bookkeeping.

    Now let's see how many inodes there are on this partition by running
    \verb=df -i /dev/sdb1=, which outputs:

    \begin{lstlisting}[gobble=3]
    Filesystem            Inodes   IUsed   IFree IUse% Mounted on
    /dev/sdb1            7325696    2312 7323384     1%  /mnt
    \end{lstlisting}
    (the numbers above are in units of 128-byte, since an inode is 128-byte long
    on my system, you can find inode size by running \verb=tune2fs -l /dev/sdb1=)

    So inodes in total occupy {\em 7325696 / (1024 / 128)}, that is {\em 915712}
    1K-blocks, and the rest of {\em 919556 - 915712}, that is {\em 3844}
    1K-blocks are used for bookkeeping.

    Besides, you may also notice that even the numbers output by {\em df} have
    some kind of inconsistency, the {\em 35970328} used plus {\em 18784952}
    available is smaller than {\em 57685532}. In fact, the {\em 2930252} blocks
    lost is reserved for the root user.

    Now let's sum up the above discussion, see the following figure: (all the
    numbers are in units of 1K-block)

    \begin{center}
    \begin{tikzpicture}
        [every node/.style={draw, rectangle, text centered, thick},
         every path/.style={draw, -latex', thick}]

        \node (par) {the whole partition(58605088)};
        \node (user) [below=of par, xshift=-5cm, yshift=-0.5cm] {user space(57685532)};
        \node (inode) [below=of par, yshift=-0.5cm] {inodes(915712)};
        \node (book) [below=of par, xshift=5cm, yshift=-0.5cm] {bookkeeping(3844)};
        \node (normal) [below=of user, xshift=-3cm, yshift=-0.5cm] {for normal user(54755280)};
        \node (root) [below=of user, xshift=3cm, yshift=-0.5cm] {for root(2930252)};

        \path (par.south) -- (user.north);
        \path (par.south) -- (book.north);
        \path (par.south) -- (inode.north);
        \path (user.south) -- (normal.north);
        \path (user.south) -- (root.north);

    \end{tikzpicture}
    \end{center}

    When creating file system with \verb=mke2fs=, the default number of inodes
    can be adjusted by \verb=-i= option, and the inode size can be adjusted by
    \verb=-I= option.

    The number of blocks reserved for root can be adjusted by \verb=-m= and
    \verb=-r= option of \verb=tune2fs=.

\end{document}

